package cas;

import valatile.ThreadUtils;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicStampedReference;

/**
 * @author Lizhentao
 * @date 2021-04-12 星期一 12:37
 */
public class ABADemo {

  static AtomicReference<Integer> atomicReference = new AtomicReference<>(100);
  static AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(100, 1);

  public static void main(String[] args) {
    final ExecutorService executorService =
      ThreadUtils.getExecutorService(3, 5, 3, 3);

    System.out.println("=========================以下是ABA问题的解决=========================");
    executorService.execute(() -> {
      final int stamp = atomicStampedReference.getStamp();
      System.out.println(Thread.currentThread().getName() + "\t第一次版本号: " + stamp);
      try {
        TimeUnit.SECONDS.sleep(1);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      System.out.println(atomicStampedReference.compareAndSet(100, 101, stamp, stamp + 1));
      System.out.println(Thread.currentThread().getName() + "\t第二次版本号: " + stamp);
    });
    executorService.execute(() -> {
      final int stamp = atomicStampedReference.getStamp();
      System.out.println(Thread.currentThread().getName() + "\t " + stamp);
      try {
        TimeUnit.SECONDS.sleep(3);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    });
    executorService.shutdown();
  }

  private static void abaCreated(ExecutorService executorService) {
    System.out.println("=========================以下是ABA问题的产生=========================");
    executorService.execute(() -> {
      atomicReference.compareAndSet(100, 101);
      atomicReference.compareAndSet(101, 100);
    });
    executorService.execute(() -> {
      try {
        TimeUnit.SECONDS.sleep(2);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      System.out.println(atomicReference.compareAndSet(100, 2019) + "\t " + atomicReference.get());
    });
    executorService.shutdown();
  }
}
